from sanic import Sanic
import aiomysql as mysql
from sanic import Blueprint
from sanic_cors import CORS
from tortoise.contrib.sanic import register_tortoise
from werkzeug.utils import ImportStringError, find_modules, import_string
from .http import http
from .listener import listen

# 初始化项目
def create_app(config=None):

    # 初始化 Sanic
    app = Sanic(__name__)

    # 解决跨域
    CORS(app)

    # 设置 config配置 项
    app.config.update(config)

    # 静态资源目录
    app.static('/static', app.config['static'])

    # 注册蓝图
    try:
        # 判断是否开启多模块
        if app.config['multi_module'] == False:
            register_blueprints('application.controller', app)
        else:
            # 遍历得到配置里面的模块
            for key, value in app.config['module'].items():
                register_blueprints('application.controller.'+key, app, value)
    except ImportStringError:
        ...

    # 注册 数据库
    register_tortoise(
        app,
        db_url=config['DB_URL'],
        modules={"models": ['application.model']},
        generate_schemas=False
    )

    # 注册服务 监听器 请求
    register_server(app)

    return app

# 注册蓝图
def register_blueprints(root, app, prefix='/'):
    # 遍历模块列表
    for name in find_modules(root, recursive=True):
        mod = import_string(name)
        # 判断是否有 bp
        if hasattr(mod, 'bp'):
            # 注册路由
            route = Blueprint.group(mod.bp, url_prefix=prefix)
            app.blueprint(route)

# 注册服务
def register_server(app):

    # 判断是否开启 注册监听器
    if app.config['listen'] == True:
        # 注册监听器
        app.register_listener(listen.before_server_start, 'before_server_start')
        app.register_listener(listen.before_server_stop, 'before_server_stop')
        app.register_listener(listen.after_server_start, 'after_server_start')
        app.register_listener(listen.after_server_stop, 'after_server_stop')

    # 请求
    @app.on_request
    async def request(request):
        http.request(request)

    # 响应
    @app.on_response
    async def response(request, response):
        http.response(request, response)